﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CommonLib;
using ElementLib.Interface;
using HalconDotNet;
using System.Windows.Forms;
namespace ElementLib
{
    public class PP : IComplexMes
    {
        private int type;
        public delegate void drawFunc(string type);
        public int Type { get { return type; } set { type = value; } }
        private List<PointPack> pointPacks= null;
        private List<string> nameList = null;
        private Output output;
        private string name;
        private static int[] existCount= new int[10];
        private SupportLine supportLine;
        private double supOffsetRow, supOffsetColumn;



        public double SupOffsetRow
        {
            get { return supOffsetRow; }
            set { supOffsetRow = value; }
        }

        public double SupOffsetColumn
        {
            get { return supOffsetColumn; }
            set { supOffsetColumn = value; }
        }

        public SupportLine SupportLine
        {
            get { return supportLine; }
            set {
                if (value == null) return;
                if (supportLine != null) 
                    supportLine.Dispose(); 
                    supportLine = value; }
        }

        public PP()
        {
            nameList = new List<string>();
        }

        public List<string> NameList
        {
            get { return nameList; }
            set
            {

                foreach (var item in value)
                {
                    nameList.Add(item);
                }
            }
        }

        public List<PointPack> PointPacks
        {
            get { return pointPacks; }
            set { pointPacks = value; }
        }
        public void ApplyChange(string mode)
        {
           
            switch (type)
            {
                case ConstValue.MEASURE_PP_DIST:
                   
                    if(mode=="add")name = "ppDist" + existCount[0]++;
                    if(supportLine != null)
                    {
                        supOffsetRow = supportLine.RowOffset;
                        supOffsetColumn = supportLine.ColumnOffset;
                    }
                    //MessageBox.Show(supOffsetColumn + "," + supOffsetRow);
                    break;
                case ConstValue.MEASURE_PP_Mid:
                    if (mode == "add") name = "ppMid" + existCount[1]++;
                    break;
                case ConstValue.MEASURE_P_FitLine:
                    if (mode == "add") name = "pFitLine" + existCount[2]++;
                    break;
                case ConstValue.MEASURE_P_Mid:
                    if (mode == "add") name = "pMid" + existCount[3]++;
                    break;
                default:
                    break;
            }
        }

        public void Dispose()
        {
            for (int i =0;i<pointPacks.Count;i++)
            {
                pointPacks[i].Dispose();
               
            }
            pointPacks.Clear();
        }

        public PP(PP pp)
        {
            supOffsetRow = pp.supOffsetRow;
            supOffsetColumn = pp.supOffsetColumn;
            name = pp.name; 
            nameList = new List<string>();
            foreach (var item in pp.nameList)
            {
                nameList.Add(item);
             }
            type = pp.type;
            output = new Output(pp.output);
            pointPacks = new List<PointPack>();
            foreach (var item in pp.pointPacks)
            {
                pointPacks.Add(new PointPack(item));
            }
        }

        public Output Rs
        {
            set { output = value; }
            get { return output; }
        }
        public bool loadElem(List<IElemPack> ieps)
        {
            pointPacks = new List<PointPack>();
            if (ieps.Count == 0)
            {
                MessageBox.Show("至少选择两条边");
                return  false;
            }
            for (int i = 0; i < ieps.Count; i++)
            {
                string name = ieps[i].GetType().FullName;
                if (name != ConstValue.TYPE_POINTPACK)
                {
                    MessageBox.Show("混有其他基本元素");
                    return false ;
                }
               
                pointPacks.Add(new PointPack((PointPack)ieps[i]));

            }
            if (ieps.Count <2)
            {
                MessageBox.Show("至少选择两条边");
                return false;
            }

            foreach (var item in ieps)
            {
                nameList.Add(item.Name);
            }
            ieps.Clear();
            return true;
        }
        public void CompleteChildElem()
        {

        }


        public string Name { get { return name; } set { name = value; } }

        /// <summary>
        /// 此方法用于非匹配阶段
        /// </summary>
        /// <param name="method"></param>
        /// <returns></returns>
        public Output Execute(FindMethod method)
        {

           
            if (pointPacks.Count < 2) throw new Exception();
            HTuple rowBegin, rowEnd, colBegin, colEnd, dist,tempRow = null,tempColumn = null;
            HObject contourTuple = null, concatLine = null, fitLineContours = null, midLineContours = null, parallelContours = null, verticalLineContours = null;
            List<Point> tempPoints = new List<Point>();
            switch (type)
            {
                case ConstValue.MEASURE_PP_DIST:
                    HOperatorSet.DistancePp(pointPacks[0].Row, pointPacks[0].Column, pointPacks[1].Row, pointPacks[1].Column, out dist);
                    supportLine = new SupportLine(pointPacks[0].P, pointPacks[1].P);
                    output = new Output((double)dist, ConstValue.DISTANCE);
                    break;
                case ConstValue.MEASURE_PP_Mid:
                    GeoMethod.PP_Mid(out midLineContours, pointPacks[0].Row, pointPacks[0].Column, pointPacks[1].Row, pointPacks[1].Column, out rowBegin, out colBegin, out rowEnd, out colEnd);
                    output = new Output(new Line(rowBegin, colBegin, rowEnd, colEnd), ConstValue.LINE);
                    break;
                case ConstValue.MEASURE_P_FitLine:
                    foreach (var pointPack in pointPacks)
                    {
        
                        if (tempRow == null)
                        {
                            tempRow = new HTuple(pointPack.Row);
                            tempColumn = new HTuple(pointPack.Column);
                        }
                        else
                        {
                            tempRow= tempRow.TupleConcat(pointPack.Row);
                            tempColumn = tempColumn.TupleConcat(pointPack.Column);
                        }
                    }
                    GeoMethod.P_FitLine(out fitLineContours, tempRow, tempColumn, out rowBegin, out colBegin, out rowEnd, out colEnd);
                    break;
                case ConstValue.MEASURE_P_Mid:
                    Point point = new Point(0.5*(pointPacks[0].Row + pointPacks[1].Row), 0.5 * (pointPacks[1].Column + pointPacks[1].Column));
                    output = new Output(point, ConstValue.POINT);
                    break;
                default:
                    break;
            }
            return output;
        }

        public void Unload()
        {
            for (int i = 0; i < pointPacks.Count; i++)
            {
                pointPacks[i].Unload();
            }

        }

        /// <summary>
        /// 用于匹配阶段，参数image和hommat2D
        /// </summary>
        /// <param name="method"></param>
        /// <returns></returns>
        public void Execute(HObject image, HTuple homMat2D, HTuple reverseHomMat2D, AddToList add, FindMethod find, AddSupline addSupline)
        {
            for (int i = 0; i < pointPacks.Count; i++)
            {
                if (pointPacks[i].IsDetectType())
                {
                    var pointPtr = find(pointPacks[i].Name, ConstValue.POINT);
                    if (pointPtr!=null)
                    {
                        //var ptr = (PointPack)pointPtr;
                        pointPacks[i] = (PointPack)pointPtr;
                        //add(pointPacks[i], ConstValue.POINT);
                    }
                    else
                    {
                        var point = pointPacks[i].Detect(image, homMat2D);
                        if (point == null) { MessageBox.Show("没有检测到"); throw new Exception(); }
                        else
                        {
                            pointPacks[i].P = new Point(point);
                            add(pointPacks[i], ConstValue.POINT);
                        }
                    }
                 
                }
                else
                {
                    var pointPtr = find(pointPacks[i].Name, ConstValue.POINT);
                    if (pointPtr == null)
                    {
                        MessageBox.Show("没有检测到"); throw new Exception();
                    }
                    else
                    {
                        PointPack pointPack = (PointPack)pointPtr;
                        pointPacks[i].P = new Point(pointPack.P);
                        add(pointPacks[i], ConstValue.POINT);
                    }
                }
            }

            if (pointPacks.Count < 2) throw new Exception();
            Output output = null;
            HTuple row, column, rowBegin, rowEnd, colBegin, colEnd, minDist, maxDist, radius, nr, nc, dist, tempRow = null, tempColumn = null;
            HObject contourTuple = null, concatLine = null, fitLineContours = null, midLineContours = null, parallelContours = null, verticalLineContours = null;
            List<Point> tempPoints = new List<Point>();
            switch (type)
            {
                case ConstValue.MEASURE_PP_DIST:
                    HOperatorSet.DistancePp(pointPacks[0].Row, pointPacks[0].Column, pointPacks[1].Row, pointPacks[1].Column, out dist);
                    supportLine = new SupportLine(pointPacks[0].P, pointPacks[1].P);
                    supportLine.InitByOffset(supOffsetRow, supOffsetColumn,homMat2D, reverseHomMat2D);
                    supportLine.SetValue(dist);
                    addSupline(supportLine);
                    output = new Output((double)dist, ConstValue.DISTANCE);
                    break;
                case ConstValue.MEASURE_PP_Mid:
                    GeoMethod.PP_Mid(out midLineContours, pointPacks[0].Row, pointPacks[0].Column, pointPacks[1].Row, pointPacks[1].Column, out rowBegin, out colBegin, out rowEnd, out colEnd);
                    output = new Output(new Line(rowBegin, colBegin, rowEnd, colEnd), ConstValue.LINE);
                    break;
                case ConstValue.MEASURE_P_FitLine:
                    foreach (var pointPack in pointPacks)
                    {

                        if (tempRow == null)
                        {
                            tempRow = new HTuple(pointPack.Row);
                            tempColumn = new HTuple(pointPack.Column);
                        }
                        else
                        {
                            tempRow = tempRow.TupleConcat(pointPack.Row);
                            tempColumn = tempColumn.TupleConcat(pointPack.Column);
                        }
                    }
                    GeoMethod.P_FitLine(out fitLineContours, tempRow, tempColumn, out rowBegin, out colBegin, out rowEnd, out colEnd);
                    break;
                case ConstValue.MEASURE_P_Mid:
                    Point point = new Point(0.5 * (pointPacks[0].Row + pointPacks[1].Row), 0.5 * (pointPacks[1].Column + pointPacks[1].Column));
                    output = new Output(point, ConstValue.POINT);
                    break;
                default:
                    break;
            }
           
        }
    }
}
